package top.lyjwn.todo.weinxin.bjnews.controller;

import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import top.lyjwn.todo.aop.log.controller.ControllerLog;
import top.lyjwn.todo.aop.token.ExemptToken;
import top.lyjwn.todo.common.template.R;
import top.lyjwn.todo.weinxin.api.bjnews.GetUserAccessToken;
import top.lyjwn.todo.weinxin.api.bjnews.GetUserCode;
import top.lyjwn.todo.weinxin.api.bjnews.PullWXUserInfo;
import top.lyjwn.todo.weinxin.bjnews.service.WXBAuthRedirectService;
import top.lyjwn.todo.weinxin.bjnews.utils.Scope;
import top.lyjwn.todo.weinxin.data.bjnews.BjnewsUserAccessToken;
import top.lyjwn.todo.weinxin.data.bjnews.WXBUser;
import top.lyjwn.todo.weinxin.exception.AesException;
import top.lyjwn.todo.weinxin.param.WXBjnewsParam;
import top.lyjwn.todo.weinxin.utils.SHA1;

import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 微信公众号控制器
 *
 * @author luoyujie
 */
@RestController
@RequestMapping("/wxb")
public class WXBUserController {

    private static final Logger log = LoggerFactory.getLogger("error");
    /**
     * 仅获取openid
     */
    private final static String STATE_TYPE_GET_OPENID = "0";
    private final static String STATE_TYPE_GET_USER_INFO = "1";
    private final static String STATE_TYPE_GET_SCAN_CODE_LOGIN = "2";


//	/**
//	 * 接入令牌
//	 */
//	@Value("${top.lyjwn.todo.weinxin.bjnews.WXBUserController.token}")
//	private String token;
//
//	/**
//	 * 是否响应接入请求
//	 */
//	@Value("${top.lyjwn.todo.weinxin.bjnews.WXBUserController.isAccess}")
//	private boolean isAccess;

    @Autowired
    private HttpServletResponse httpServletResponse;


    @Autowired(required = false)
    private WXBAuthRedirectService wxbAuthRedirectService;

    @Autowired
    private WXBjnewsParam wxBjnewsParam;

    @Autowired
    private GetUserCode getUserCode;

    @Autowired
    private GetUserAccessToken getUserAccessToken;

    @Autowired
    private PullWXUserInfo pullWXUserInfo;

    /**
     * 获取授权跳转url
     *
     * @return
     */
    @ExemptToken
    @ControllerLog(description = "获取授权的跳转url")
    @RequestMapping("/wxuser/getUrl")
    public R<String> getUrl() {
        R<String> template = R.init(String.class).ok("请求成功");
        template.setData(wxBjnewsParam.getDomain_name() + "/wxb/wxuser/getCode?state=");
        return template;
    }

    /**
     * 获取用户授权code
     *
     * @param state
     * @throws IOException
     */
    @ExemptToken
    @ControllerLog(description = "获取用户授权code")
    @RequestMapping("/wxuser/getCode")
    public void getCode(String state) throws IOException {
        String url;
        switch (state == null ? "" : state) {
            case STATE_TYPE_GET_OPENID:
                url = getUserCode.getUrl(wxBjnewsParam.getAuth_domain_name() + "/wxb/wxuser/getCode/redirect", Scope.SNSAPI_BASE,
                        state);
                break;
            case STATE_TYPE_GET_USER_INFO:
                url = getUserCode.getUrl(wxBjnewsParam.getAuth_domain_name() + "/wxb/wxuser/getCode/redirect", Scope.SNSAPI_USERINFO,
                        state);
                break;
            case STATE_TYPE_GET_SCAN_CODE_LOGIN:
                url = getUserCode.getUrl(wxBjnewsParam.getAuth_domain_name() + "/wxb/wxuser/getCode/redirect", Scope.SNSAPI_USERINFO,
                        STATE_TYPE_GET_SCAN_CODE_LOGIN);
                break;
            default:
                url = getUserCode.getUrl(wxBjnewsParam.getAuth_domain_name() + "/wxb/wxuser/getCode/redirect", Scope.SNSAPI_BASE,
                        state);
                break;
        }
        httpServletResponse.sendRedirect(url);
    }

    /**
     * 拉取用户信息
     *
     * @param code
     * @param state
     * @return
     */
    @ExemptToken
    @ControllerLog(description = "拉取用户信息")
    @RequestMapping(value = "/wxuser/getCode/redirect", method = RequestMethod.GET)
    public void authRedirect(String code, String state) {
        // 获取accessToken
        JSONObject apiResponseToJSON = getUserAccessToken.getResultJSONObject(code);
        if (apiResponseToJSON == null) {
            log.error("授权登录无效 可能是code已失效 Response:" + apiResponseToJSON.toJSONString());
        }
        BjnewsUserAccessToken accessToken = BjnewsUserAccessToken.builder(apiResponseToJSON);
        if (wxbAuthRedirectService != null) {
            switch (state == null ? "" : state) {
                case STATE_TYPE_GET_SCAN_CODE_LOGIN:
                    // 拉取用户信息
                    JSONObject responseToJSON = pullWXUserInfo.getResultJSONObject(accessToken);
                    WXBUser wxbUser = WXBUser.builder(responseToJSON);
                    wxbAuthRedirectService.scanCodeLogin(wxbUser);
                    break;
                case STATE_TYPE_GET_USER_INFO:
                    // 拉取用户信息
                    JSONObject responseToJSON_ = pullWXUserInfo.getResultJSONObject(accessToken);
                    WXBUser wxbUser_ = WXBUser.builder(responseToJSON_);
                    wxbAuthRedirectService.redirect(httpServletResponse, wxbUser_);
                    break;
                default:
                    wxbAuthRedirectService.redirect(httpServletResponse, accessToken);
            }
        }

        // 构造响应模板
//		DTOObjectTemplate<Map<String,Object>> template = DTOObjectTemplate.SUCCESS("拉取用户信息成功");
//		Map<String,Object> map = new ConcurrentHashMap<>();
//		map.put("wxbUser",wxbUser);
//		map.put("state",state);
//		template.setData(map);
//		return template;
    }

    @ExemptToken
    @ControllerLog(description = "接入验证")
    @RequestMapping(value = "/join/up", method = RequestMethod.GET)
    public String joinUp(String signature, String timestamp, String nonce, String echostr) throws AesException {
        // "8EGz7nanC7NIKkUoEEyaMTqYtv3iQRZXT19Y0AUSw2u"
        if (wxBjnewsParam.isAccess()) {
            String sha1 = SHA1.getSHA1(wxBjnewsParam.getToken(), timestamp, nonce);
            if (signature.equals(sha1)) {
                return echostr;
            }
        }
        return "";
    }
}
